#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# -----------------------------------------------------------------------------
# chandler.py
#
# 
# -----------------------------------------------------------------------------

from debug import *

from cglobal import *

class fbasic():
    """
     @class function basic to supply a base for 
    """
    def __init__(self):
        self.flags={ 'depth':DEFAULT_DEPTH,
                    'filter':'',
                    'silent':0
                    }
        self.semi_line = 0
        self.cur_line = 0
        self.def_lines=[]   # 用于存储预定义的line
        self.code_lines={}  # 找不到有效注释时，通过code lines存储语句
        self.fcall_map={}     # 用于存储所调用的函数
        self.token_list=[]  # token的堆栈
        self.gvarin_map={}  # 输入的全局变量的map
        self.expr=""
        self.gvarout_map={}  # 输出的全局变量的map
        self.param_map={}  # 参数的map
        self.comment_map={} # 注释

    def reset(self):
        # 清零
        self.fcall_map.clear()
        self.gvarin_map.clear()
        self.expr=""
        self.gvarout_map.clear()
        self.param_map.clear()

    def reset_param(self, pstr):
        raw_plist = pstr.split(')')[0].split('(')[-1].split(',')
        plist = [p.split()[-1] for p in raw_plist]
        #print('Resetting...', pstr, plist, self.gvarout_map)
        self.param_map.clear()
        # 如果已有的列表中包含某个参数，而该参数不在原型中，说明是之前的声明留下的，改为全局变量
        for k, v in self.gvarout_map.items():
            if v == VTYPE_PARAM:
                if not k in plist:
                    self.gvarout_map[k] = VTYPE_GLOBAL
        pass

    # 初始化
    def init(self):
        del self.token_list[:]

    # 获取栈顶
    def top(self, offset=0):
        return self.token_list[-1-offset]

    # raw push
    def rpush(self, token):
        self.token_list.append(token)

    # raw pop
    def rpop(self):
        return self.token_list.pop()

    # 系统解析函数
    def parse(self):
        pass
    
    # 压入相关操作，并根据类型进行解析
    def push(self, token):
        self.token_list.append(token)
        if ENABLE_GENERIC_DEBUG==1: print('push', self.len(), token)
        self.parse()

    # 针对token list的pop操作
    def pop(self):
        pass
    
    def len(self):
        return len(self.token_list)

    def trace(self):
        if ENABLE_GENERIC_DEBUG==1: print('tklist', self.token_list)

    def flag_set(self, index, value):
        self.flags[index] = value

    def flag_get(self, index):
        if (self.flags.has_key(index)):
            return self.flags[index]
        else:
            return 0

    def semil_update(self, line):
        self.semi_line = line

    def semil_get(self):
        return self.semi_line

    # 更新当前行
    def curl_get(self):
        return self.cur_line

    def curl_update(self, p):
        for i in range(1, len(p)):
            #print("TR", p.lineno(i))
            if (p.lineno(i) != 0):
                self.cur_line=p.lineno(i)
    
    def declaration_update(self, line, code):
        #print "declaration update ", line, code
        self.reset_param(code)
        self.def_lines.append([line, code])

    def declaration_get(self, off=0):
        return self.def_lines[-1-off][1]

    # 
    def code_push(self, line, code):
        self.code_lines[line] = code

    def code_pop(self, start, end):
        ret = ""
        # 此时需要注意range是一个开区间
        for i in range(start, end+1):
            if self.code_lines.has_key(i):
                ret += self.code_lines[i]
                ret += ';'
        return ret[0:-1]

    def code_trace(self):
        for elem in self.code_lines.iterkeys():
            if ENABLE_GENERIC_DEBUG==1: print '#L', elem, self.code_lines[elem]

    # 更新当前的序列
    def update(self, p, trim=0, sep=' '):
        """
        @param p 需要进行合并的表达式列表
        @trim 尾部需要跳过的元素数量
        """
        if USELIST==1:
            p[0]=[]
            for i in range(1, len(p) - trim):
                p[0].append(p[i])
        else:
            updatestr(p, trim, sep)

        #p.set_lineno(0, p.lineno(1))
        p.set_lineno(0, p.lineno(1), p.endlineno(-1))

        self.curl_update(p)
        #print p.lineno(0), p.endlineno(0), p.linespan(1), p.linespan(-1)
        #print("curline", get_curline())

    # 判定指定的分支中是否需要额外压入语句 （用于更新lineno的数值）
    def extra_get(self, p, si):
        # 此处不需要考虑 越界的问题
        if (ENABLE_YTOOL_DEBUG==1): print '===ex get', p[si], self.semil_get()
        if (p[si][-2] != '}'
                and p[si].count(';') <=1
                ):
            return 1
        return 0

    def sextra_push(self, p, si, start=0, end=0):
        if (ENABLE_YTOOL_DEBUG==1): print '===sex', p[si], self.semil_get()
        semi = self.semil_get()
        if (p[si][-2] != '}'
                and p[si].count(';') <=1
                ):
            elem = ['SINGLE', p.lineno(si), semi, p[si]]
            if (start != 0):
                elem[1] = start
            if (end != 0):
                elem[2] = end
            if (elem[1] == 0):
                elem[1] = semi
            #print elem
            self.push(elem)
            return elem[2]
        return 0

    # 如果需要，将额外的元素事先压入
    # 通过判断元素的第一个字符是不是'{'如果是，说明已经作为{}压入，不管
    # 通过判断元素的最后一个有效字符是不是'}'如果是，说明已经作为{}压入，不进行额外处理
    #    如果不是，再判断是否是其他的复合语句，
    #        如果是（;数量>1），也不压入
    #        如果不是复合语句，将statement压入
    #    
    def extra_push(self, p, si, start=0):
        if (ENABLE_YTOOL_DEBUG==1): print '===ex', p[si], self.semil_get()
        if (p[si][-2] != '}'
                and p[si].count(';') <=1
                ):
            #if (start == 0):
            #    # 由p.lineno(si)换为p.lineno(1)
            #    #self.push(['{}', p.lineno(1), self.semil_get(), p[si]])
            #    self.push(['SINGLE', p.lineno(si), self.semil_get(), p[si]])
            #else:
            #    self.push(['{}', start, start, p[si]])

            self.push(['SINGLE', p.lineno(si), p.endlineno(si), p[si]])
            return p.endlineno(si)
        return 0

    def gvarout_push(self, name, value=VTYPE_GLOBAL):
        # 输出变量的操作
        #print("===gvarout", name, value)
        try:
            if (value > self.gvarout_map[name] ):
                self.gvarout_map[name] = value
                #print('===++', name, value)
        except Exception,e:
            self.gvarout_map[name] = value
            #print('=====', name, value)

    def var_dump(self):
        for k in self.gvarout_map.iterkeys():
            print k, self.gvarout_map[k]

    def gvarin_push(self, name, value=0):
        # 压入读入的变量
        if '.' in name:
            # self.expr += name.split('.')[0]+' '
            self.expr += name.replace('[]', '').split('.')[0]+' '
        else:
            self.expr += name
        #self.gvarin_map[name] = line
        if ENABLE_GENERIC_DEBUG==1: print('=====gvin', name, value, self.expr)

    def param_push(self, name, value=VTYPE_PARAM):
        # 压入参数
        #print("===P", name)
        self.param_map[name] = value

    def fun_push(self, line, name):
        # 在yacc中压入函数调用，使用map存储，自动合并相同调用
        #self.fun_list.append([line, name])
        self.fcall_map[name.rstrip()] = line
        #print 'function calling', line, name

    # 获取注释
    def get_comment(self, start):
        comment = ''
        cm = self.comment_map
        if (cm.has_key(start)):
            comment = cm[start]
        elif (cm.has_key(start-1)):
            comment = cm[start-1]
        return comment

    # 获取函数的注释深度
    def get_comment_depth(self, start):
        import re 
        comment = self.get_comment(start)
        
        if comment!='':
            width_str = re.search('@depth\s+\d+', comment)
            try:
                # 确定模式匹配之后，获取后面的数值
                depth = int(width_str.group(0).split()[1])
                return depth
            except:
                return DEFAULT_DEPTH
        return DEFAULT_DEPTH


########################################################

